home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / tex / style / misc / epic.sty < prev    next >
Text File  |  1995-11-25  |  27KB  |  567 lines

  1. \makeatletter
  2. \typeout{%
  3. Enhancements to Picture Environment. Version 1.2 - Released June 1, 1986}
  4. \typeout{Verbessert durch M. Hoppe, 3. Okt. 1990.}
  5. % Untere Beschriftung von \grid korrigiert. (Stellen mit MH gekennzeichnet)
  6. %----------------------------------------------------------------------
  7. % Copyright (C) podar@sbcs (Sunil Podar) July 14,1986.
  8. % You may use this file in whatever way you wish. You are requested to
  9. % leave this notice intact, and report any bugs, enhancements, comments,
  10. % suggestions, etc. to:
  11. % USmail: Sunil Podar,Dept. of Computer Science,SUNY at Stony Brook,NY 11794.
  12. %  CSNET: podar@sbcs.csnet
  13. %   ARPA: podar%suny-sb.csnet@csnet-relay.arpa
  14. %   UUCP: {allegra, hocsd, philabs, ogcvax}!sbcs!podar
  15. %----------------------------------------------------------------------
  16. % This file contains implementation of:
  17. % \multiputlist \matrixput      \grid           \picsquare
  18. % \dottedline   \dashline       \drawline       \jput
  19. % \putfile
  20. % Environments: dottedjoin, dashjoin and drawjoin
  21. %
  22. % For documentation, see the accompanying manual.
  23. %----------------------------------------------------------------------
  24. % usage: \multiputlist(x,y)(delta-x,delta-y)[tbrl]{item1,item2,item3,.....}
  25. % \lop and \lopoff taken from TeXbook.
  26. %----------------------------------------------------------------------
  27. \def\lop#1\to#2{\expandafter\lopoff#1\lopoff#1#2}
  28. \long\def\lopoff,#1,#2\lopoff#3#4{\def#4{#1}\def#3{,#2}}
  29. \def\@@mlistempty{,}
  30. \newif\iflistnonempty
  31. \def\multiputlist(#1,#2)(#3,#4){\@ifnextchar
  32. [{\@imultiputlist(#1,#2)(#3,#4)}{\@imultiputlist(#1,#2)(#3,#4)[]}}
  33.  
  34. \long\def\@imultiputlist(#1,#2)(#3,#4)[#5]#6{{%
  35. \@xdim=#1\unitlength \@ydim=#2\unitlength
  36. \listnonemptytrue \def\@@mlist{,#6,} % need this for end condition
  37. \loop
  38. \lop\@@mlist\to\@@firstoflist
  39. \@killglue\raise\@ydim\hbox to\z@{\hskip
  40. \@xdim\@imakepicbox(0,0)[#5]{\@@firstoflist}\hss}
  41. \advance\@xdim #3\unitlength\advance\@ydim #4\unitlength
  42. \ifx\@@mlist\@@mlistempty \listnonemptyfalse\fi
  43. \iflistnonempty
  44. \repeat\relax
  45. \ignorespaces}}
  46. %----------------------------------------------------------------------
  47. % two-dimensional version of \multiput
  48. % \matrixput(0,0)(20,0){5}(0,20){3}{\circle{2}}
  49. %----------------------------------------------------------------------
  50. \newcount\@@multicnt
  51. \def\matrixput(#1,#2)(#3,#4)#5(#6,#7)#8#9{%
  52. \ifnum#5>#8\@matrixput(#1,#2)(#3,#4){#5}(#6,#7){#8}{#9}%
  53. \else\@matrixput(#1,#2)(#6,#7){#8}(#3,#4){#5}{#9}\fi}
  54.  
  55. %% here #5 >= #8
  56. \long\def\@matrixput(#1,#2)(#3,#4)#5(#6,#7)#8#9{{\@killglue%
  57. \@multicnt=#5\relax\@@multicnt=#8\relax%
  58. \@xdim=0pt%
  59. \@ydim=0pt%
  60. \setbox\@tempboxa\hbox{\@whilenum \@multicnt > 0\do {%
  61. %%\typeout{\the\@multicnt, \the\@@multicnt}%
  62. \raise\@ydim\hbox to \z@{\hskip\@xdim #9\hss}%
  63. \advance\@multicnt \m@ne%
  64. \advance\@xdim #3\unitlength\advance\@ydim #4\unitlength}}%
  65. \@xdim=#1\unitlength%
  66. \@ydim=#2\unitlength%
  67. \@whilenum \@@multicnt > 0\do {%
  68. \raise\@ydim\hbox to \z@{\hskip\@xdim \copy\@tempboxa\hss}%
  69. \advance\@@multicnt \m@ne%
  70. \advance\@xdim #6\unitlength\advance\@ydim #7\unitlength}%
  71. \ignorespaces}}
  72. %----------------------------------------------------------------------
  73. %\grid(width,height)(delta-width,delta-height)[initial-X-integer,initial-Y-integer]
  74. % example: 1. \put(0,0){\grid(95,100)(9.5,10)}
  75. %          2. \put(0,0){\grid(100,100)(10,5)[-10,0]}
  76. %          or \put(0,0){\tiny \grid(100,100)(5,5)[0,0]}% numbers in \tiny font
  77. %----------------------------------------------------------------------
  78. \newcount\d@lta
  79. \newdimen\@delta
  80. \newdimen\@@delta
  81. \newcount\@gridcnt
  82. %\newcount\unitl@ngth \unitl@ngth=\unitlength    % Umwandlung von
  83. % <dimen>\unitlength in sp       MH
  84. %\newcount\b@selineskip \b@selineskip=\baselineskip % Umwandlung von
  85. % <skip>\baselineskip in sp      MH
  86. %\divide\b@selineskip by \unitl@ngth % Um soviel \unitlength muß der Text
  87. % unter dem unteren Rand stehen  MH
  88.  
  89.  
  90. \def\grid(#1,#2)(#3,#4){\@ifnextchar [{\@igrid(#1,#2)(#3,#4)}%
  91. {\@igrid(#1,#2)(#3,#4)[@,@]}}
  92.  
  93. \long\def\@igrid(#1,#2)(#3,#4)[#5,#6]{%
  94. \makebox(#1,#2){%
  95. \@delta=#1pt\@@delta=#3pt\divide\@delta \@@delta\d@lta=\@delta%
  96. \advance\d@lta \@ne\relax\message{grid=\the\d@lta\space x}%
  97. %% copied the definition of \line(0,1){#2} for some efficiency!.
  98. \multiput(0,0)(#3,0){\d@lta}{\hbox to\z@{\hskip -\@halfwidth \vrule
  99.          \@width \@wholewidth \@height #2\unitlength \@depth \z@\hss}}%
  100. \ifx#5@\relax\else%
  101. \global\@gridcnt=#5%
  102. \multiput(0,0)(#3,0){\d@lta}{%
  103. \makebox(0,-2)[t]{\number\@gridcnt\global\advance\@gridcnt by #3}}% Schwein!
  104. \global\@gridcnt=#5%
  105. \multiput(0,#2)(#3,0){\d@lta}{%
  106. \makebox(0,0)[b]{\number\@gridcnt\vspace{2mm}\global\advance\@gridcnt by #3}}%
  107. \fi%
  108. \@delta=#2pt\@@delta=#4pt\divide\@delta \@@delta\d@lta=\@delta%
  109. \advance\d@lta \@ne\relax\message{\the\d@lta . }%
  110. %% copied the definition of \line(1,0){#1} for some efficiency!.
  111. \multiput(0,0)(0,#4){\d@lta}{\vrule \@height \@halfwidth \@depth \@halfwidth
  112.          \@width #1\unitlength}%
  113. \ifx#6@\relax\else
  114. \global\@gridcnt=#6%
  115. \multiput(0,0)(0,#4){\d@lta}{%
  116. \makebox(0,0)[r]{\number\@gridcnt\ \global\advance\@gridcnt by #4}}%
  117. \global\@gridcnt=#6%
  118. \multiput(#1,0)(0,#4){\d@lta}{%
  119. \makebox(0,0)[l]{\ \number\@gridcnt\global\advance\@gridcnt by #4}}%
  120. \fi}}
  121. %----------------------------------------------------------------------
  122. % \picsquare is a centered square of dimensions governed by \thinlines,
  123. % \thicklines or \linethickness declarations.
  124. \def\picsquare{\hskip -0.5\@wholewidth%
  125. \vrule height \@halfwidth depth \@halfwidth width \@wholewidth}
  126. %
  127. % just a square dot with reference point at bottom-left
  128. \def\picsquare@bl{\vrule height \@wholewidth depth \z@  width \@wholewidth}
  129. %----------------------------------------------------------------------
  130. % \begin{dottedjoin}{interdot-gap in units}
  131. % .....
  132. % \end{dottedjoin}
  133. % \begin{dashjoin}{dash-length in units}{interdotgap in each dash}
  134. % .....
  135. % \end{dashjoin}
  136. % \begin{drawjoin}
  137. % .....
  138. % \end{drawjoin}
  139. % \jput(x,y){character}
  140. % \dottedline[opt. dotcharacter]{dotgap in units}(x1,y1)(x2,y2)...(xN,yN)
  141. % \dashline[#]{dash-length}[opt. dotgap](x1,y1)(x2,y2)...(xN,yN)
  142. % \drawline[#](x1,y1)(x2,y2)...(xN,yN)
  143. %----------------------------------------------------------------------
  144. % definitions for *join environment. had to do all this mess because of
  145. % optional arguments.
  146. %----------------------------------------------------------------------
  147. \newif\if@jointhem \global\@jointhemfalse
  148. \newif\if@firstpoint \global\@firstpointtrue
  149. \newcount\@joinkind
  150. %\newenvironment{dottedjoin}[1]%[opt char]{dotgap}
  151. %{\global\@jointhemtrue \gdef\dotgap@join{#1}\global\@joinkind=0\relax}%
  152. %{\global\@jointhemfalse \global\@firstpointtrue}
  153. %----------------------------------------------------------------------
  154. \def\dottedjoin{\global\@jointhemtrue \global\@joinkind=0\relax
  155.   \bgroup\@ifnextchar[{\@idottedjoin}{\@idottedjoin[\picsquare@bl]}}
  156. \def\@idottedjoin[#1]#2{\gdef\dotchar@join{#1}\gdef\dotgap@join{#2}}
  157. \def\enddottedjoin{\global\@jointhemfalse \global\@firstpointtrue\egroup}
  158. %----------------------------------------------------------------------
  159. \def\dashjoin{\global\@jointhemtrue \global\@joinkind=1\relax
  160.   \bgroup\@ifnextchar[{\@idashjoin}{\@idashjoin[\dashlinestretch]}}
  161. \def\@idashjoin[#1]#2{\edef\dashlinestretch{#1}\gdef\dashlen@join{#2}%
  162. \@ifnextchar[{\@iidashjoin}{\gdef\dotgap@join{}}}
  163. \def\@iidashjoin[#1]{\gdef\dotgap@join{#1}}
  164. \let\enddashjoin\enddottedjoin
  165. %----------------------------------------------------------------------
  166. \def\drawjoin{\global\@jointhemtrue \global\@joinkind=2\relax
  167.   \bgroup\@ifnextchar[{\@idrawjoin}{}}
  168. \def\@idrawjoin[#1]{\def\drawlinestretch{#1}}
  169. \let\enddrawjoin\enddottedjoin
  170. %----------------------------------------------------------------------
  171. %% this is equiv to \put(x,y){#1} when not in {dot*join} environment.
  172. \long\def\jput(#1,#2)#3{{\@killglue\raise#2\unitlength\hbox to \z@{\hskip
  173. #1\unitlength #3\hss}\ignorespaces}
  174. \if@jointhem
  175.  \if@firstpoint \gdef\x@one{#1} \gdef\y@one{#2} \global\@firstpointfalse
  176.  \else\ifcase\@joinkind
  177.                 \@dottedline[\dotchar@join]{\dotgap@join\unitlength}%
  178. (\x@one\unitlength,\y@one\unitlength)(#1\unitlength,#2\unitlength)
  179.                 \or\@dashline[\dashlinestretch]{\dashlen@join}[\dotgap@join]%
  180. (\x@one,\y@one)(#1,#2)
  181.                 \else\@drawline[\drawlinestretch](\x@one,\y@one)(#1,#2)\fi
  182.     \gdef\x@one{#1} \gdef\y@one{#2}
  183.  \fi
  184. \fi}
  185. %----------------------------------------------------------------------
  186. \newdimen\@dotgap
  187. \newdimen\@ddotgap
  188. \newcount\@x@diff
  189. \newcount\@y@diff
  190. \newdimen\x@diff
  191. \newdimen\y@diff
  192. \newbox\@dotbox
  193. \newcount\num@segments
  194. \newcount\num@segmentsi
  195. \newif\ifsqrt@done
  196. %% from sqrtandstuff func basically need \num@segments.
  197. %% given a deltax, deltay and dotgap, it calculates \num@segments = number of
  198. %% segments along the hypotenuse. used by \dottedline & \dashline.
  199. %% It finishes quickly if any of deltax or deltay are zero or close to zero.
  200. \def\sqrtandstuff#1#2#3{
  201. \ifdim #1 <0pt \@x@diff= -#1 \else\@x@diff=#1\fi
  202. \ifdim #2 <0pt \@y@diff= -#2 \else\@y@diff=#2\fi
  203. %% @diff's will be positive and diff's will retain their sign.
  204. \@dotgap=#3 \divide\@dotgap \tw@
  205. \advance\@x@diff \@dotgap \advance\@y@diff \@dotgap% for round-off errors
  206. \@dotgap=#3
  207. \divide\@x@diff \@dotgap \divide\@y@diff \@dotgap
  208. \sqrt@donefalse
  209. \ifnum\@x@diff < 2
  210.    \ifnum\@y@diff < 2 \num@segments=\@x@diff \advance\num@segments \@y@diff
  211.                       \sqrt@donetrue
  212.         \else\num@segments=\@y@diff \sqrt@donetrue\fi
  213.    \else\ifnum\@y@diff < 2 \num@segments=\@x@diff \sqrt@donetrue\fi
  214. \fi
  215. \ifsqrt@done \ifnum\num@segments=\z@ \num@segments=\@ne\fi\relax
  216.  \else \ifnum\@y@diff >\@x@diff
  217.                  \@tempcnta=\@x@diff \@x@diff=\@y@diff \@y@diff=\@tempcnta
  218.        \fi              %exchange @x@diff & @y@diff, so now @x@diff > @y@diff
  219.   \num@segments=\@y@diff
  220.   \multiply\num@segments \num@segments
  221.   \multiply\num@segments by 457
  222.   \divide\num@segments \@x@diff
  223.   \advance\num@segments by 750 % for round-off, going to divide by 1000.
  224.   \divide\num@segments \@m
  225.   \advance\num@segments \@x@diff
  226.                 %num@segments = @x@diff + (0.457*sqr(@y@diff)/@x@diff)
  227. \fi}
  228. %----------------------------------------------------------------------
  229. % \dottedline[opt. char]{interdot gap in units}(x1,y1)(x2,y2)....(xN,yN)
  230. %----------------------------------------------------------------------
  231. %% Used the following construction earlier but that results in box memory
  232. %% full much too soon although it works perfectly.
  233. %% \setbox\@dotbox\vbox to\z@{\vss \hbox to\z@{\hss #1\hss}\vss}\relax}
  234. %% The cenetering of characters is achieved by substracting half the ht, wd
  235. %% of character from the (x,y) coordinates where they are to be put. We
  236. %% chose to use a macro for the ``dot'' instead of \copy\box to save memory at
  237. %% the expense of extra cpu, since memory becomes an issue very soon.
  238. %% \picsquare is already centered, whereas other characters, except \circle,
  239. %% will not be cenetered, hence to handle them all in a similar fashion,
  240. %% used \picsquare@bl.
  241. %
  242. % kind of tail recursion.
  243. \def\dottedline{\@ifnextchar [{\@idottedline}{\@idottedline[\picsquare@bl]}}
  244. \def\@idottedline[#1]#2(#3,#4){\@ifnextchar (%
  245. {\@iidottedline[#1]{#2}(#3,#4)}{\relax}}
  246. \def\@iidottedline[#1]#2(#3,#4)(#5,#6){\@dottedline[#1]{#2\unitlength}%
  247. (#3\unitlength,#4\unitlength)(#5\unitlength,#6\unitlength)%
  248. \@idottedline[#1]{#2}(#5,#6)}
  249. %
  250. %% user not supposed to use this directly. arguments in absolute dimensions.
  251. %% need to pass absolute dimens here because dashline calls dottedline and
  252. %% can supply only absolute dimensions.
  253. \long\def\@dottedline[#1]#2(#3,#4)(#5,#6){{%
  254. \x@diff=#5\relax\advance\x@diff by -#3\relax
  255. \y@diff=#6\relax\advance\y@diff by -#4\relax
  256. \sqrtandstuff{\x@diff}{\y@diff}{#2}
  257. \divide\x@diff \num@segments
  258. \divide\y@diff \num@segments
  259. \advance\num@segments \@ne     % to put the last point at destination.
  260. %%\typeout{num@segments= \the\num@segments}
  261. \setbox\@dotbox\hbox{#1}% just to get the dimensions of the character.
  262. \@xdim=#3 \@ydim=#4
  263. \ifdim\ht\@dotbox >\z@% otherwise its a circle.
  264.   \advance\@xdim -0.5\wd\@dotbox
  265.   \advance\@ydim -0.5\ht\@dotbox
  266.   \advance\@ydim .5\dp\@dotbox\fi
  267. %%circle's have a ht=0, this is one way I could think of to catch circles.
  268. %%following equiv to \multiput(\@xdim,\@ydim)(\x@diff,\y@diff){\num@segments}{#1}
  269. %%with arguments in absolute dimensions.
  270. \@killglue
  271. \loop \ifnum\num@segments > 0
  272. \unskip\raise\@ydim\hbox to\z@{\hskip\@xdim #1\hss}%
  273. \advance\num@segments \m@ne\advance\@xdim\x@diff\advance\@ydim\y@diff%
  274. \repeat
  275. \ignorespaces}}
  276. %----------------------------------------------------------------------
  277. % \dashline[#]{dash-length}[optional dotgap](x1,y1)(x2,y2)...(xN,yN)
  278. % The minimum # of dashes put is 2, one at either end point; dash-length is
  279. % reduced accordingly if necessary. Also have to some dirty work to account
  280. % for stretch & shrink.
  281. % \renewcommand{\dashlinestretch}{-50}  %ONLY INTEGERS PERMITTED.
  282. %----------------------------------------------------------------------
  283. \def\dashlinestretch{0} %well, could have used a counter.
  284. \def\dashline{\@ifnextchar [{\@idashline}{\@idashline[\dashlinestretch]}}
  285. \def\@idashline[#1]#2{\@ifnextchar [{\@iidashline[#1]{#2}}%
  286. {\@iidashline[#1]{#2}[\@empty]}} %\@empty needed-- later checked with \ifx
  287. \def\@iidashline[#1]#2[#3](#4,#5){\@ifnextchar (%
  288. {\@iiidashline[#1]{#2}[#3](#4,#5)}{\relax}}
  289. %
  290. \def\@iiidashline[#1]#2[#3](#4,#5)(#6,#7){%
  291. \@dashline[#1]{#2}[#3](#4,#5)(#6,#7)%
  292. \@iidashline[#1]{#2}[#3](#6,#7)}
  293. %
  294. \long\def\@dashline[#1]#2[#3](#4,#5)(#6,#7){{%
  295. \x@diff=#6\unitlength \advance\x@diff by -#4\unitlength
  296. \y@diff=#7\unitlength \advance\y@diff by -#5\unitlength
  297. %% correction to get actual width since the dash-length as taken in arguement
  298. %% is the center-to-center of the end-points.
  299. \@tempdima=#2\unitlength \advance\@tempdima -\@wholewidth
  300. \sqrtandstuff{\x@diff}{\y@diff}{\@tempdima}
  301. \ifnum\num@segments <3 \num@segments=3\fi% minimum number of dashes I can plot
  302. % is 2, 1 at either end, thus min num@segments is 3 (including 'empty dash').
  303. \@tempdima=\x@diff \@tempdimb=\y@diff
  304. \divide\@tempdimb by\num@segments
  305. \divide\@tempdima by\num@segments
  306. %% ugly if-then-else. If optional dotgap specified, then use it otherwise
  307. %% make a solid looking dash.
  308. {\ifx#3\@empty \relax
  309.     \ifdim\@tempdima < 0pt \x@diff=-\@tempdima\else\x@diff=\@tempdima\fi
  310.     \ifdim\@tempdimb < 0pt \y@diff=-\@tempdimb\else\y@diff=\@tempdimb\fi
  311.     \ifdim\x@diff < 0.3pt %it's a vertical dashline
  312.            \ifdim\@tempdimb > 0pt
  313.                 \global\setbox\@dotbox\hbox{\hskip -\@halfwidth \vrule
  314.                  \@width \@wholewidth \@height \@tempdimb}
  315.            \else\global\setbox\@dotbox\hbox{\hskip -\@halfwidth \vrule
  316.                  \@width \@wholewidth \@height\z@ \@depth -\@tempdimb}\fi
  317.        \else\ifdim\y@diff < 0.3pt %it's a horizontal dashline
  318.                \ifdim\@tempdima >0pt
  319.                   \global\setbox\@dotbox\hbox{\vrule \@height \@halfwidth
  320.                                 \@depth \@halfwidth \@width \@tempdima}
  321.                 \else\global\setbox\@dotbox\hbox{\hskip \@tempdima
  322.                          \vrule \@height \@halfwidth \@depth \@halfwidth
  323.                                  \@width -\@tempdima \hskip \@tempdima}\fi
  324.             \else\global\setbox\@dotbox\hbox{%
  325. \@dottedline[\picsquare]{0.98\@wholewidth}(0pt,0pt)(\@tempdima,\@tempdimb)}
  326. \fi\fi
  327. \else\global\setbox\@dotbox\hbox{%
  328. \@dottedline[\picsquare]{#3\unitlength}(0pt,0pt)(\@tempdima,\@tempdimb)}
  329. \fi}
  330. \advance\x@diff by -\@tempdima % both have same sign
  331. \advance\y@diff by -\@tempdimb
  332. %
  333. %%here we correct the number of dashes to be put by reducing them
  334. %%appropriately. (num@segments*\@wholewidth) is in some way the slack we
  335. %%have,and division by dash-length gives the reduction. reduction =
  336. %%(2*num@segments*\@wholewidth)/dash-length (num@segments includes empty ones)
  337. \@tempdima=\num@segments\@wholewidth \@tempdima=2\@tempdima
  338. \@tempcnta=\@tempdima \@tempdima=#2\unitlength \@tempdimb=0.5\@tempdima
  339. \@tempcntb=\@tempdimb \advance\@tempcnta by \@tempcntb % round-off error
  340. \divide\@tempcnta by\@tempdima \advance\num@segments by -\@tempcnta
  341. %
  342. \ifnum #1=0 \relax\else\ifnum #1 < -100
  343.   \typeout{***dashline: reduction > -100 percent implies blankness!***}
  344. \else\num@segmentsi=#1 \advance\num@segmentsi by 100
  345.      \multiply\num@segments by\num@segmentsi \divide\num@segments by 100
  346. \fi\fi
  347. %
  348. \divide\num@segments by 2 % earlier num@segments included 'empty dashes' too.
  349. \ifnum\num@segments >0 %      %   if =0 then don't divide => \x@diff & \y@diff
  350.  \divide\x@diff by\num@segments%   remain same.
  351.  \divide\y@diff by\num@segments
  352.  \advance\num@segments by\@ne %for the last segment for which I subtracted
  353.                              %\@tempdima & \@tempdimb from \x@diff & \y@diff
  354.  \else\num@segments=2 % one at each end.
  355. \fi
  356. %%\typeout{num@segments finally = \the\num@segments}
  357. %% equiv to \multiput(#4,#5)(\x@diff,\y@diff){\num@segments}{\copy\@dotbox}
  358. %% with arguements in absolute dimensions.
  359. \@xdim=#4\unitlength \@ydim=#5\unitlength
  360. \@killglue
  361. \loop \ifnum\num@segments > 0
  362. \unskip\raise\@ydim\hbox to\z@{\hskip\@xdim \copy\@dotbox\hss}%
  363. \advance\num@segments \m@ne\advance\@xdim\x@diff\advance\@ydim\y@diff%
  364. \repeat
  365. \ignorespaces}}
  366. %----------------------------------------------------------------------
  367. %%1.00   .833333  .80  .75  .66666   .60  .50  .40  .33333    .25  .20  .16666
  368. %% .916666 .816666 .775 .708333 .633333 .55 .45 .366666 .291666 .225 .183333
  369. %% 0.0
  370. %%0.083333
  371. %% the first line has absolute slopes corresponding to various permissible
  372. %% integer combinations representing slopes. The second line is the midpoint
  373. %% of all those slopes (attempted to show them in the middle of two entries).
  374. %%
  375. %% \lineslope(x@diff dimen, y@diff dimen)
  376. %% Given base (x@diff) and height (y@diff) in dimensions, determines the
  377. %% closest available slope and returns the two required integers in \@xarg and
  378. %% \@yarg. The given base and height can be ANYTHING, -ve or +ve, or even 0pt.
  379. %% \lineslope knows about (0,1) and (1,0) slopes too and returns correct
  380. %% values if the conditions regarding x@diff & y@diff are obeyed. (see NOTE).
  381. %% Used by \drawline. This is the simplest and only way I could figure out
  382. %% to accomplish it!.
  383. %% NOTE: both the dimensions (x@diff & y@diff) must be in SAME units and the
  384. %% larger of the two dimensions must be atleast 1pt (i.e. 65536sp). To avoid
  385. %% dividing by 0, I make the larger dimension = 1pt if it is < 1pt.
  386. %% will need a similar one for vectors, or maybe this can be used. For
  387. %% vectors the range is -4, 4 unlike lines where it is -6, 6.
  388. \newif\if@flippedargs
  389. \def\lineslope(#1,#2){%
  390. \ifdim #1 <0pt \@xdim= -#1 \else\@xdim=#1\fi
  391. \ifdim #2 <0pt \@ydim= -#2 \else\@ydim=#2\fi
  392. %%\typeout{xdim,ydim= \the\@xdim, \the\@ydim}
  393. \ifdim\@xdim >\@ydim \@tempdima=\@xdim \@xdim=\@ydim \@ydim=\@tempdima
  394. \@flippedargstrue\else\@flippedargsfalse\fi% x < y
  395. \ifdim\@ydim >1pt \@tempcnta=\@ydim
  396.             \divide\@tempcnta by 65536% now \@tempcnta=integral part of #1.
  397.             \divide\@xdim \@tempcnta\fi
  398. \ifdim\@xdim <.083333pt \@xarg=1 \@yarg=0
  399.  \else\ifdim\@xdim <.183333pt   \@xarg=6 \@yarg=1
  400.  \else\ifdim\@xdim <.225pt      \@xarg=5 \@yarg=1
  401.  \else\ifdim\@xdim <.291666pt   \@xarg=4 \@yarg=1
  402.  \else\ifdim\@xdim <.366666pt   \@xarg=3 \@yarg=1
  403.  \else\ifdim\@xdim <.45pt       \@xarg=5 \@yarg=2
  404.  \else\ifdim\@xdim <.55pt       \@xarg=2 \@yarg=1
  405.  \else\ifdim\@xdim <.633333pt   \@xarg=5 \@yarg=3
  406.  \else\ifdim\@xdim <.708333pt   \@xarg=3 \@yarg=2
  407.  \else\ifdim\@xdim <.775pt      \@xarg=4 \@yarg=3
  408.  \else\ifdim\@xdim <.816666pt   \@xarg=5 \@yarg=4
  409.  \else\ifdim\@xdim <.916666pt   \@xarg=6 \@yarg=5
  410.        \else                    \@xarg=1 \@yarg=1%
  411. \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
  412. \if@flippedargs\relax\else\@tempcnta=\@xarg \@xarg=\@yarg \@yarg=\@tempcnta\fi
  413. \ifdim #1 <0pt \@xarg= -\@xarg\fi
  414. \ifdim #2 <0pt \@yarg= -\@yarg\fi
  415. %%\typeout{closest slope integers = \the\@xarg, \the\@yarg}
  416. }
  417. %----------------------------------------------------------------------
  418. % usage: \drawline[#](x1,y1)(x2,y2)....(xN,yN)
  419. %                        % # is an optional integer between -100 & infinity.
  420. % \renewcommand{\drawlinestretch}{-50}  %ONLY INTEGERS PERMITTED.
  421. %----------------------------------------------------------------------
  422. \newif\if@toosmall
  423. \newif\if@drawit
  424. \newif\if@horvline
  425. \def\drawlinestretch{0} %well, could have used a counter.
  426. % kind of tail recursion.
  427. \def\drawline{\@ifnextchar [{\@idrawline}{\@idrawline[\drawlinestretch]}}
  428. \def\@idrawline[#1](#2,#3){\@ifnextchar ({\@iidrawline[#1](#2,#3)}{\relax}}
  429. \def\@iidrawline[#1](#2,#3)(#4,#5){\@drawline[#1](#2,#3)(#4,#5)
  430. \@idrawline[#1](#4,#5)}
  431. %
  432. \def\@drawline[#1](#2,#3)(#4,#5){{%
  433. \x@diff=#4\unitlength \advance\x@diff by -#2\unitlength
  434. \y@diff=#5\unitlength \advance\y@diff by -#3\unitlength
  435. %% override any linethickness declarations, and since horiz & vertical lines
  436. %% come out thinner than the slanted ones, assign slightly larger values.
  437. %% default values are: thinlines=0.4pt, thicklines=0.8pt
  438. \ifx\@linefnt\tenln \linethickness{0.5pt} \else \linethickness{0.9pt}\fi
  439. \lineslope(\x@diff,\y@diff)% returns the two integers in \@xarg & \@yarg.
  440. %------
  441. \@toosmalltrue
  442. {\ifdim\x@diff <\z@ \x@diff=-\x@diff\fi
  443.  \ifdim\y@diff <\z@ \y@diff=-\y@diff\fi
  444.  \ifdim\x@diff >10pt \global\@toosmallfalse\fi
  445.  \ifdim\y@diff >10pt \global\@toosmallfalse\fi}
  446. %------
  447. %% For efficiency, if the line is horiz or vertical then we draw it in one
  448. %% shot, only if the stretch is not -ve and the line is not too small.
  449. \@drawitfalse\@horvlinefalse
  450. \ifnum#1 <0 \relax\else\@horvlinetrue\fi
  451. \if@toosmall\@horvlinetrue\fi% to get 'or' condition. We necessarily draw a
  452. % solid line if the line is too small ignoring any -ve stretch.
  453. \if@horvline
  454.   \ifdim\x@diff =0pt \put(#2,#3){\ifdim\y@diff >0pt \@linelen=\y@diff \@upline
  455.                                 \else\@linelen=-\y@diff \@downline\fi}%
  456.   \else\ifdim\y@diff =0pt
  457.           \ifdim\x@diff >0pt \put(#2,#3){\vrule \@height \@halfwidth \@depth
  458.                                 \@halfwidth \@width \x@diff}
  459.                 \else \put(#4,#5){\vrule \@height \@halfwidth \@depth
  460.                                 \@halfwidth \@width -\x@diff}\fi
  461.        \else\@drawittrue\fi\fi % construct the line explicitly
  462. \else\@drawittrue\fi
  463. %-------------------------------
  464. \if@drawit
  465. \ifnum\@xarg< 0 \@negargtrue\else\@negargfalse\fi
  466. \ifnum\@xarg =0 \setbox\@linechar%
  467. \hbox{\hskip -\@halfwidth \vrule \@width \@wholewidth \@height 10.2pt
  468.  \@depth \z@}
  469. \else \ifnum\@yarg =0 \setbox\@linechar%
  470. \hbox{\vrule \@height \@halfwidth \@depth \@halfwidth \@width 10.2pt}
  471. \else \if@negarg \@xarg -\@xarg \@yyarg -\@yarg
  472.         \else \@yyarg \@yarg\fi
  473. \ifnum\@yyarg >0 \@tempcnta\@yyarg \else \@tempcnta -\@yyarg\fi
  474. \setbox\@linechar\hbox{\@linefnt\@getlinechar(\@xarg,\@yyarg)}%
  475. \fi\fi
  476. %------
  477. \if@toosmall% => it isn't a horiz or vert line and is toosmall.
  478.   \@dottedline[\picsquare]{.98\@wholewidth}%
  479. (#2\unitlength,#3\unitlength)(#4\unitlength,#5\unitlength)%
  480. \else
  481. %% following is neat. The last segment takes \wd\@linechar & \ht\@linechar
  482. %% so plot the line as though it were from (#2,#3) to
  483. %% (#4-\wd\@linechar,#5-\ht\@linechar) (i.e. for positive slope; of course,
  484. %% signs are reversed for other slopes). For horizontal & vertical dashes we
  485. %% don't have to subtract the ht & wd resp. since they are already centered.
  486. \ifnum\@xarg=0\relax\else\ifdim\x@diff >\z@ \advance\x@diff -\wd\@linechar
  487.   \else\advance\x@diff \wd\@linechar\fi\fi
  488. \ifnum\@yarg=0\relax\else\ifdim\y@diff >\z@\advance\y@diff -\ht\@linechar
  489.   \else\advance\y@diff \ht\@linechar\fi\fi
  490. \ifdim\x@diff <\z@ \@x@diff=-\x@diff \else\@x@diff=\x@diff\fi
  491. \ifdim\y@diff <\z@ \@y@diff=-\y@diff \else\@y@diff=\y@diff\fi
  492. %%\typeout{x@diff,y@diff=\the\x@diff , \the\y@diff}
  493. \num@segments=0 \num@segmentsi=0
  494. \ifdim\wd\@linechar >1pt
  495.  \num@segmentsi=\@x@diff \divide\num@segmentsi \wd\@linechar\fi
  496. \ifdim\ht\@linechar >1pt
  497.  \num@segments=\@y@diff \divide\num@segments \ht\@linechar\fi
  498. \ifnum\num@segmentsi >\num@segments \num@segments=\num@segmentsi\fi
  499. \advance\num@segments \@ne %to account for round-off error
  500. %
  501. \ifnum #1=0 \relax \else\ifnum #1 < -99
  502.   \typeout{***drawline: reduction <= -100 percent implies blankness!***}
  503. \else\num@segmentsi=#1 \advance\num@segmentsi by 100
  504.      \multiply\num@segments \num@segmentsi
  505.      \divide\num@segments by 100
  506. \fi\fi
  507. %%\typeout{num@segments after = \the\num@segments}
  508. %
  509. \divide\x@diff \num@segments
  510. \divide\y@diff \num@segments
  511. \advance\num@segments \@ne %for the last segment for which I subtracted
  512.                           %\wd & \ht of \@linechar from \@x@diff & \@y@diff.
  513. %%\typeout{numseg,x@diff,y@diff= \the\num@segments, \the\x@diff, \the\y@diff}
  514. %
  515. \@xdim=#2\unitlength \@ydim=#3\unitlength
  516. \if@negarg \advance\@xdim -\wd\@linechar\fi
  517. \ifnum\@yarg <0 \advance\@ydim -\ht\@linechar\fi
  518. %% equiv to following with arguements in absolute dimensions.
  519. %%\multiput@abs(\@xdim,\@ydim)(\x@diff,\y@diff){\num@segments}{\copy\@linechar}
  520. \@killglue
  521. \loop \ifnum\num@segments > 0
  522. \unskip\raise\@ydim\hbox to\z@{\hskip\@xdim \copy\@linechar\hss}%
  523. \advance\num@segments \m@ne\advance\@xdim\x@diff\advance\@ydim\y@diff%
  524. \repeat
  525. \ignorespaces
  526. \fi%the if of @toosmall
  527. \fi}}% for \if@drawit
  528. %----------------------------------------------------------------------
  529. %usage: \putfile{datafile}{OBJECT}
  530. % The OBJECT is plotted at EACH of the coordinates read from the datafile.
  531. % The idea of these macros is to generate (x,y) pairs using some program
  532. % and then directly use those coordinates. Since TeX doesn't have real
  533. % floating point calculations, it is much more efficient and accurate to do
  534. % things this way. One can also use the unix facility 'spline' now to
  535. % generate smooth curves with equidistant ``dots''.
  536. % NOTE: the external file of coordinates must have x y pairs with a space
  537. % between them. Also it is suggested that some extension such as '.put'
  538. % be used for such datafiles to distinguish them in which case it must
  539. % be explicitely specified in the 1st argument so that TeX doesn't look
  540. % for a .tex extension.
  541. % The % char remains valid as a comment char and such lines are ignored;
  542. % however, there should be atleast one space after the second entry if a
  543. % comment is on the same line as data since % eats up the newline.
  544. %-----------------------------------------------------------------------
  545. \long\def\splittwoargs#1 #2 {(#1,#2)}
  546. %
  547. \newif\if@stillmore
  548. \newread\@datafile
  549. \long\def\putfile#1#2{\openin\@datafile = #1
  550. \@stillmoretrue
  551. \loop
  552. \ifeof\@datafile\relax\else\read\@datafile to\@dataline\fi
  553. %if file nonexistent, do nothing.
  554. \ifeof\@datafile\@stillmorefalse
  555. \else\ifx\@dataline\@empty \relax
  556.      \else
  557. \expandafter\expandafter\expandafter\put\expandafter\splittwoargs%
  558. \@dataline{#2}
  559.      \fi
  560. \fi
  561. \if@stillmore
  562. \repeat
  563. \closein\@datafile
  564. }
  565. %----------------------------------------------------------------------
  566. \makeatother
  567.